﻿using System;
using System.Collections.Generic;
using System.Text;



namespace Open.Data.Persistence
{
    public class ComplexExpression : Expression
    {
        //Working variables
        private Boolean _expectOperator;

        //Properties
        protected List<Expression> Expressions { get; set; }
        protected List<ExpressionOperator> Operators { get; set; }

        //Constructors
        public ComplexExpression()
        {
            Expressions = new List<Expression>();
            Operators = new List<ExpressionOperator>();
            _expectOperator = false;
        }

        //Methods
        public void AddExpression(Expression expression)
        {
            if (_expectOperator) throw new Exception("An operator should be added to the complex expression.");
            Expressions.Add(expression);
            _expectOperator = true;
        }

        public void AddColumn(Column column)
        {
            AddExpression(column);
        }

        public void AddOperator(ExpressionOperator op)
        {
            if (!_expectOperator) throw new Exception("A column should be added to the complex expression.");
            Operators.Add(op);
            _expectOperator = false;
        }

        public IEnumerable<Expression> GetChildExpressions()
        {
            foreach (Expression expression in Expressions)
            {
                yield return expression;
            }
        }

        public IEnumerable<ExpressionOperator> GetChildOperators()
        {
            foreach (ExpressionOperator op in Operators)
            {
                yield return op;
            }
        }

        public virtual void Validate()
        {
            if (Expressions.Count < 2) throw new PersistenceException("Column Expression count must be at least two.");
            if (Operators.Count < 1) throw new PersistenceException("Operators count must be at least one.");
            if (Expressions.Count - 1 != Operators.Count) throw new PersistenceException("Number of Operators must be one less than number of Column Expressions.");
        }

        public override IEnumerable<IParameter> GetParameters()
        {
            foreach (Expression expression in Expressions)
            {
                foreach (IParameter parameter in expression.GetParameters())
                {
                    yield return parameter;
                }
            }
        }

        public override void AppendHashCode(StringBuilder builder)
        {
            foreach (Expression expression in Expressions)
            {
                expression.AppendHashCode(builder);
            }

            foreach (ExpressionOperator op in Operators)
            {
                builder.Append(op.ToString());
            }
        }
    }
}
